﻿using System.Collections.Generic;
using System;
using Castle.Services.Transaction;
using Castle.Core.Logging;

namespace Inovout.Business
{
    public abstract class BaseWorkItem : IWorkItem
    {
        protected BaseWorkItem()
        {
            //functions = new List<IFunction>();
        }
        public Function Function
        {get;set;}
        
        internal IExtendedLogger logger;

        //private List<IFunction> functions;
        //public IList<IFunction> Functions
        //{
        //    get { return functions; }
        //}
        internal IViewDataDictionary viewData;
        protected IViewDataDictionary ViewData
        {
            get
            {
                return viewData;
            }
            set
            {
                SetViewData(value);
            }
        }
        protected virtual void SetViewData(IViewDataDictionary value)
        {
            viewData = value;
        }
        public void Execute()
        {
            ITransactionManager manager = ComponentRegistry.Resolve<ITransactionManager>();

            ITransaction transaction = manager.CreateTransaction(
                TransactionMode.Requires, IsolationMode.Unspecified);

            transaction.Begin();

            bool rolledback = false;

            try
            {

                Run();

                if (transaction.IsRollbackOnlySet)
                {
                    logger.DebugFormat("Rolling back transaction {0}", transaction.GetHashCode());

                    rolledback = true;
                    transaction.Rollback();
                }
                else
                {
                    logger.DebugFormat("Committing transaction {0}", transaction.GetHashCode());

                    transaction.Commit();
                }
            }
            catch (TransactionException ex)
            {
                if (logger.IsFatalEnabled)
                {
                    logger.Fatal("Fatal error during transaction processing", ex);
                }

                throw;
            }
            catch (Exception ex)
            {
                if (!rolledback)
                {
                    if (logger.IsDebugEnabled)
                        logger.DebugFormat("Rolling back transaction {0} due to exception on method", transaction.GetHashCode());

                    transaction.Rollback();
                }
                logger.Error("WorkItem run error.",ex);
                throw ex;
            }
            finally
            {
                manager.Dispose(transaction);
            }
        }


        protected abstract void Run();
        public bool CanExecute()
        {
            throw new NotImplementedException();
        }
        internal IGuiAction guiAction;

        protected void View()
        {
            View(null);
        }
        protected void View(object model)
        {
            View(null, model);
        }
        protected void View(string viewName)
        {
            View(viewName, null);
        }

        protected void View(string viewName, object model)
        {
            guiAction.View(CreateWorkItemContext(viewName, model));
        }
        private WorkItemContext CreateWorkItemContext(string viewName, object model)
        {
            //if (string.IsNullOrEmpty(viewName))
            //{
            //    viewName = this.GetType().Name.Replace("WorkItem", string.Empty);
            //}
            WorkItemContext workItemContext = new WorkItemContext(this);
            workItemContext.ViewName = viewName;
            //workItemContext.Functions = functions.ToArray();
            workItemContext.ViewData = viewData;
            workItemContext.ViewData.Model = model;

            return workItemContext;
        }
        protected void Dialog(string viewName, object model)
        {
            guiAction.Dialog(CreateWorkItemContext(viewName, model));

        }

        public void Message(string msg)
        {
            guiAction.Message(msg);
        }


    }
}
